package classload;

import java.util.Scanner;
import java.lang.reflect.*;

/**
 * @author DCSGO
 * @version 1.0
 * 类加载
 */

/*
类加载
反射机制是java实现动态语言的关键，也就是通过反射实现类动态加载。
1.静态加载: 编译时加载相关的类，如果没有则报错，依赖性太强
2.动态加载: 运行时加载需要的类，如果运行时不用该类，即使不存在该类，也不报错，降低了依赖性

类加载时机
1.当创建对象时(new) -> 静态加载
2.当子类被加载时，父类也加载 -> 静态加载
3.调用类中的静态成员时 -> 静态加载
4.通过反射 -> 动态加载
*/
public class ClassLoad_ {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入选择：");
        String input = scanner.next();
        switch (input) {
            case "1":
                Dog dog = new Dog();//没有该类就会报错
                dog.hi();
                break;
            case "2":
                Class cls = Class.forName("Person");
                Object o = cls.newInstance();
                Method method = cls.getMethod("hi");
                method.invoke(o);
                break;
            default:
                System.out.println("do nothing...");
        }
    }
    /* 没有 Dog 类 没有 Person 类 编译后:
    ClassLoad_.java:31: 错误: 找不到符号
            Dog dog = new Dog();//没有该类就会报错
            ^
      符号:   类 Dog
      位置: 类 ClassLoad_
    ClassLoad_.java:31: 错误: 找不到符号
                Dog dog = new Dog();//没有该类就会报错
                              ^
      符号:   类 Dog
      位置: 类 ClassLoad_
    注: ClassLoad_.java使用了未经检查或不安全的操作。
    注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
    2 个错误
    */
    //可以看到对于反射 Person 类所执行的相关操作并没有出现什么
    //错误但 Dog 由于是静态加载 所以报了两个错

    /* 添加 Dog 类后 
    注: ClassLoad_.java使用了未经检查或不安全的操作。
    注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
    */
    //可以通过编译了 但会有警告信息

    /*
    请输入选择：
    2
    Exception in thread "main" java.lang.ClassNotFoundException: Person
            at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
            at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
            at java.lang.Class.forName0(Native Method)
            at java.lang.Class.forName(Class.java:264)
            at ClassLoad_.main(ClassLoad_.java:35)
    */
    //只有当程序运行到使用了反射机制的代码时才会抛出相关异常


}

class Dog {
    public void hi() {
        System.out.println("小狗汪汪叫~");
    }
}
